--------------------------------------------------------------------------------
Chapter 2
--------------------------------------------------------------------------------


CONTENT:
---------------------------------
Part one: Introduction to Quake C
---------------------------------

Chapter 2: A TOUR OF QUAKE-C

 A) COMPILATION AND EXECUTION

A Quake-C program is a set of one or more functions and data, known as
SOURCE CODE, written by the programmer with an editor program.  The source
code is stored in a file with an arbitrary name, by convention followed by 
the suffix '.qc'.

To render the Quake-C program intelligible to and executable by Quake, the 
source code must be processed in a number of steps.

First, The Quake-C source code is scanned by the Quake-C Compiler. The 
Compiler is itself a program which, according to the grammatical rules 
of the Quake-C language, parses and analyses the source code into an 
intermediate form known as Progs.Dat file. 

*Note:  If you are building models (.MDL), The program Modelgen will parse 
	the same source as QCC, so frame indexes will keep their symbolic 
	names when compiled into the program Code.

Second, Quake will use the Progs.Dat file and interpret it internally to the 
game and execute the appropriate code.

To compile the Quake-C code, it is necessary to follow a few basic steps:

	To modify the quake program code, set up a new game directory 
	parallel with id1, and containing a "progs" subdirectory.  Copy all 
	the .qc files and progs.src into that, and just run qcc from that 
	directory. That will compile all of the files listed in progs.src 
	and (if there aren't any errors) generate a new progs.dat file in 
	the parent directory.

	As a simple test, open the client.qc file, go to the ClientObituary 
	function at the end, and change some of the messages.

	The directory structure will look something like:

	/quake/quake.exe
	/quake/id1/
	/quake/mygame/progs.dat
	/quake/mygame/progs/progs.src
	/quake/mygame/progs/world.qc
	/quake/mygame/progs/client.qc
	/quake/mygame/progs/... etc ...

	Run quake with "-game mygame", which will cause quake to look for 
	data in the mygame directory before falling back to id1. In this 
	example, it will find the new progs.dat from mygame, and take 
	everything else from id1.  You can type "path" at the quake console 
	to verify the current search order of directories and pak files.  
	THIS WILL ONLY WORK WITH A REGISTERED VERSION OF QUAKE.

If you are compiling a Model (.MDL) with some Quake-C code, here are some 
basic steps to follow:

	Once you have completed make sure that all these files are in one 
	directory: 

	base.tri	//Copy of knife.tri 
	knife.tri 	//Actual 3-d model file
	skin.lbm	//Texture for knife
	knife.qc	//Quake-C file for knife. (what it does)



Then simply run modelgen knife.qc which will then create a knife.mdl file 
which quake reads when running the game.

If you have done everything right you should now see a knife.mdl file in the 
same directory.

Here are some points you need to be aware of when using Quake-C:

Source files are processed sequentially without dumping any state, so if a 
defs file is the first one processed, the definitions will be available to 
all other files.

The language is strongly typed and there are no casts.

(DEFINITION cast:  An operation which converts the type of its operand to a 
specified type.  In the cast operation (float)x, the type of X is converted 
to floating-point.)

(DEFINITION type:  The nature of a VARIABLE, decared by a programmer to 
specify the range of values a variable can take as well as the operations 
which can be performed on it.)

Anything that is initialized is assumed to be constant, and will have 
immediates folded into it. If you change the value, your program will 
malfunction.  All uninitialized globals will be saved to savegame files.


Functions cannot have more than eight parameters.

(DEFINITION function:  A body of code comprising a FUNCTION HEADER immediately
followed by a COMPOUND STATEMENT.  A function name is an external object; a
function can therefore be called from any other function, to which execution
control is returned when the called function has finished.)

Error recovery during compilation is minimal.  It will skip to the next global 
definition, so you will never see more than one error at a time in a given 
function.  All compilation aborts after ten error messages.

Names can be defined multiple times until they are defined with an 
initialization, allowing functions to be prototyped before their definition.

(DEFINITION name:  The collective term used to describe all VARIABLE names,
preprocessor macros and symbolic constants.)

Example:

void()	MyFunction;		// the prototype

void()	MyFunction =		// the initialization
{
	dprint ("we're here\n");
};


 B) SIMPLE QUAKE-C PROGRAMS

The Following is the minimal Quake-C function:

	Void() T_Damage =
	{
	};

Every Quake-C program must consist of one or more functions.  The code shown
above is a function.  The function name is T_Damage.  Functions cannot have 
more than eight parameters.

The parentheses, (), enclose the names of PARAMETERS which may be received by
the function.  There are no parameter names here, but the rules for inclusion
of these are given in chapter 3.

(DEFINITION formal parameter:  Synonymous with PARAMETER, meaning a VARIABLE
defined in a FUNCTION header.  The Value of the actual parameter supplied in
the function call is copied to the formal parameter.)

(DEFINITION variable:  A memory location used to hold data of a particular
TYPE, represented by an IDENTIFIER and capable of being repeatedly assigned
to.)

(DEFINITION identifier:  The name given to a VARIABLE when it is decared.)

The curly braces {} are a COMPOUND STATEMENT:  in fact a null compound
statement because they do not contain any statements in the example above.

On execution, the function, as might be expected, does nothing.

The following function is slightly more meaningful:

	void()	T_Damage =
	{
	  dprint ("Bang! Your dead!\n");
	};

DPRINT is a call to a Builtin Function.  It is not part of the Quake-C 
language itself.  The dprint is nonetheless a statement, which is and must 
be terminated with a semicolon.  the text within the parentheses is an a 
ARGUMENT to the called builtin function DPRINT.

Executing this program causes the text:

	Bang! Your dead!

to appear on Quake Console.  the \n is Quake-C's way of specifying advance
to a new line, causes the output to advance one line after the text is 
displayed.

 C) FUNCTIONS

A function is a body of Quake-C code executed from another part of the 
program by means of a FUNCTION CALL.  Functions usually contain code to 
perform a specific action.  Instead of duplicating that code at every point 
in the program where the action is required, the programmer writes calls to 
the function, where the single definition of the code resides.  Every Quake-C 
program is a collection of functions.

The following is a simple general form for DECLARING functions:

	<RETURNTYPE> (arg1, arg2,...,arg8) <FUNC_NAME>;

Declaring a function makes it available to all functions defined after it. 
It MUST be defined at some point, or the Quake-C compiler complain's.
You must also put a semi-colon at the end of the Declare. An example of 
declaring a function is as follows:

void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;

VOID is the Return Type.

(entity targ, entity inflictor, entity attacker, float damage) is the
paramater list. There are 4 arguments in the argument list with this 
function inside the parenthesis.

T_Damage is the Function Name. 

Note the Semi-colon at the end of the line.

(DEFINITION return type: The TYPE of the DATA OBJECT returned by a FUNCTION
to the point of its call.)

(DEFINITION argument list: The full list of FORMAL PARAMETERS defined in a 
functions header.)

(DEFINITION function call:  A FUNCTION name, followed by a parenthesised list 
of ARGUMENTS and terminated by a semicolon.  The code of function named is 
executed and, when it is finished, the STATEMENT following the function call 
is executed.)

The following is a simple general form for DEFINING functions:

	<RETURNTYPE> (arg1, arg2, ..., arg8) <FUNCT_NAME> =
	{
		<statements>
	};

Defining a function assigns a group of statements to it. An example of 
defining a function is as follows:

void(entity targ, entity inflictor, entity attacker, float damage) T_Damage =
{
        local   vector  dir;
        local   entity  oldself;
        local   float   save;
        local   float   take;

        if (!targ.takedamage)
                return;

        save = ceil(targ.armortype*damage);
        if (save >= targ.armorvalue)
        {
                save = targ.armorvalue;
                targ.armortype = 0;     // lost all armor
                
        }
        
        targ.armorvalue = targ.armorvalue - save;
        take = ceil(damage-save);


//LOTS MORE COOL DAMAGE STUFF (but snipped for space reasons)

};

VOID is the Return Type.

there are 4 arguments in the argument list with this function inside the 
parenthesis.

T_Damage is the Function Name. 

Note the Assignment Operator(=) at the end of the first line.

The code in between the outer curly braces {}; is the STATEMENTS. (meat of the
function). You MUST use a semi-colon <;> after the LAST Curly brace.

Calling a function (function call) is just the name of the function, followed
by a comma-seperated list of arguments, enclosed in parentheses. 


The following is a simple general form for CALLING functions:

	<FUNCT_NAME> (arg1, arg2, ..., arg8);

<FUNCT_NAME> This is the NAME of the function you want to call.

(arg1, arg2, ..., arg8) These are the arguments you want to send to the
			function.

Note the semi-colon at the end of the line.

Here is an example of how Calling a function is used in Quake-C. (look for
the function called T_Damage:


/*
==============================================================================

MULTI-DAMAGE

Collects multiple small damages into a single damage

==============================================================================
*/


entity multi_ent;
float multi_damage;

void() ClearMultiDamage=
{
        multi_ent = world;
        multi_damage = 0;
};

void() ApplyMultiDamage=
{
        if (!multi_ent)
                return;
        T_Damage (multi_ent, self, self, multi_damage);
};


Every Quake-C function can and should be fully described in three parts using 
a declaration, call and definition.  Fuller rules for use of these constructs 
are given in Chapter 3.

Comments are included in the program between the /* and */ delimiters.  The 
text of comments has no effect on the execution of the program. The compiler 
ignores comments and does not generate object code for them.

Syntax errors with comments can have serious effects. If the trailing */ is 
left out, the compiler will keep searching for it until the end of the 
program and the compilation process will fail.

If the characters in /* or */ are seperated by one or more spaces, for 
example * /, the compiler will not recognise the text between them as 
comments.  The comment delimiters are pairs of characters.

Comments must NOT be nested:

	/*COMMENT TEXT /* nested */ in error */

In this case, the first */ ends the comment.  When the compiler tries to 
interpret IN ERROR */, a compilation error results.

Quake-C allows the alternative double-slash comment form:

// This line (ONLY) is a comment

Because the comment is not explicitly terminated, this form is convenient 
and less error-prone for writing short comments then the 
conventional /* ... */ sequence.


D) DATA REPRESENTATION (SIMPLE)

DISCLAIMER:  This section may not even be relevent to Quake-C. It is
	     included here in the hopes that it is. It may be deleted
	     in a future revision. If anyone can shed any light on the
	     subject please send e-mail to me at Rudeseal@hemi.com.

Variables in Quake-C are data objects that may change in value.  A variable
is given a name by means of a definition, which allocates storage space for
the data and associates the storage location with the variable name.

The Quake-C language defines four fundamental representations of data:

	integer
	character
	floating-point
	double floating-point

Each of these is associated with a special type specifier:

	int	specifies an integer variable
	char	specifies a character variable
	float	specifies a fractional-number variable
	double	specifies a fractional-number variable with
		more decimal places

Any of the type specifiers may be qualified with the type qualifier CONST,
which specifies that the variable must not be changed after it is initialised.

A data definition is of the following general form:

	<type-specifier> <name>;

A variable name is also called an identifier. The following are some
examples of simple data definitions in Quake-C:

	int	goals;		// integer variable
	char	c;		// character value eg: 'b'
	float	balance;	// bank balance
	const	double x = 5;	// high-precision variable
				// value fixed when set